package wowrl.engine;

import java.awt.Point;
import java.util.Map;
import java.util.Vector;

import wowrl.data.Item;
import wowrl.data.ItemFactory;
import wowrl.data.Mob;
import wowrl.data.MobFactory;
import wowrl.data.Player;
import wowrl.data.Terrain;
import wowrl.data.TerrainFactory;
import wowrl.data.WOWRL_Data;

public class WOWRL_Engine {
	private WOWRL_Data gameState;
	private TerrainFactory terrainFactory;
	private ItemFactory itemFactory;
	private MobFactory mobFactory;
	private DungeonGenerator dungeonGenerator;
	
	public WOWRL_Engine(WOWRL_Data gameState)
	{
		this.gameState = gameState;
		
		terrainFactory = new TerrainFactory(this);
		itemFactory = new ItemFactory(this);
		mobFactory = new MobFactory(this);
		dungeonGenerator = new DungeonGenerator(gameState,terrainFactory,itemFactory,mobFactory);
		
		initializePlayer();
		dungeonGenerator.CreateDungeon();
	}
	
	public void initializePlayer(){
		//Create the player (default location 5,5)
		gameState.player = new Player(this, new Point(5,5));

		//TEST - Give the player an apple
		gameState.player.inventory.add(itemFactory.createApple());
	}

	public void movePlayer(int xOffset, int yOffset)
	{
		//Abort if there isn't actually a move being made
		if (xOffset == 0 && yOffset == 0) { return; }
				
		//Calculate the new location
		Point newLocation = new Point (gameState.getPlayerLocation().x + xOffset , gameState.getPlayerLocation().y + yOffset);
					
		//Validate the new location
		if (!gameState.validateLocation(newLocation)) { return; }
		
		//Check if solid
		if (gameState.map.terrain[newLocation.x][newLocation.y].isSolid){
			//Interact with the terrain
			//NOT IMPLEMENTED YET
		}
		else
		{			
			//Interact with any mobs
			if (gameState.map.mobs[newLocation.x][newLocation.y] != null)
			{
				gameState.map.mobs[newLocation.x][newLocation.y].interact();				
			}
			else
			{
				//If there are no mobs, attempt to move, interact with objects if successful
				if (attemptMove(newLocation)==true)
				{
					//Interact with objects - NOT IMPLEMENTED	
				}
			}			
		}
	}
	
	public boolean attemptMove(Point newLocation)
	{		
		//Move the player
		gameState.setPlayerLocation(newLocation);
		
		//Check if the move was successful
		if (gameState.player.location != newLocation)
		{
			return false;
		}
		else
		{
			return true;
		}		
	}
	
	public void pickupItem(Point location, Item itemGained)
	{
		this.gameState.player.inventory.add(itemGained);		
	}
	
	public Point getPlayerLocation()
	{		
		return gameState.getPlayerLocation();
	}
	
	/*
	public Map<String,InventoryItem> getInventory()
	{
		return gameState.player.inventory;
	}
	*/
	
	public Point playerLocation()
	{
		return gameState.player.location;
	}
	
	public int getPlayerDisplayTileNumber()
	{
		return gameState.player.displayTileNumber;
	}
	
	public boolean isTerrainTiled(int row, int col)
	{
		if (getTerrain(row, col).displayTileNumber == 1057) {return true;}
		return false;
	}
	
	public int adjustedTerrainDisplayTileNumber(int row, int col)
	{	
		Terrain thisTile = getTerrain(row,col);
		
		//Special offset to make walls flow seamlessly
		if (thisTile.isWall)
		{
			int offset;
			
			//NA. Isolated segment, should never occur
			offset=-1;
			
			//0. Up,Down
			if (getTerrain(row, col+1).isWallExtension && getTerrain(row, col-1).isWallExtension
					&& !getTerrain(row+1, col).isWallExtension && !getTerrain(row-1, col).isWallExtension )
			{ offset = 0; }
			
			//1. Left,Right
			else if (!getTerrain(row, col+1).isWallExtension && !getTerrain(row, col-1).isWallExtension
					&& getTerrain(row+1, col).isWallExtension && getTerrain(row-1, col).isWallExtension )
			{ offset = 1; }
			
			//2. CORNER: Down,Right
			else if (getTerrain(row, col+1).isWallExtension && !getTerrain(row, col-1).isWallExtension
					&& getTerrain(row+1, col).isWallExtension && !getTerrain(row-1, col).isWallExtension )
			{ offset = 2; }
			
			//3. CORNER: Down,Left
			else if (getTerrain(row, col+1).isWallExtension && !getTerrain(row, col-1).isWallExtension
					&& !getTerrain(row+1, col).isWallExtension && getTerrain(row-1, col).isWallExtension )
			{ offset = 3; }
			
			//4. CORNER: Up,Right
			else if (!getTerrain(row, col+1).isWallExtension && getTerrain(row, col-1).isWallExtension
					&& getTerrain(row+1, col).isWallExtension && !getTerrain(row-1, col).isWallExtension )
			{ offset = 4; }
			
			//5. CORNER: Up,Left
			else if (!getTerrain(row, col+1).isWallExtension && getTerrain(row, col-1).isWallExtension
					&& !getTerrain(row+1, col).isWallExtension && getTerrain(row-1, col).isWallExtension )
			{ offset = 5; }

			//6. PLUS-JOINT
			else if (getTerrain(row, col+1).isWallExtension && getTerrain(row, col-1).isWallExtension
					&& getTerrain(row+1, col).isWallExtension && getTerrain(row-1, col).isWallExtension )
			{ offset = 6; }
			
			//7. T-JOINT: Up,Left,Right
			else if (!getTerrain(row, col+1).isWallExtension && getTerrain(row, col-1).isWallExtension
					&& getTerrain(row+1, col).isWallExtension && getTerrain(row-1, col).isWallExtension )
			{ offset = 7; }
			
			//8. T-JOINT: Down,Left,Right
			else if (getTerrain(row, col+1).isWallExtension && !getTerrain(row, col-1).isWallExtension
					&& getTerrain(row+1, col).isWallExtension && getTerrain(row-1, col).isWallExtension )
			{ offset = 8; }

			//9. T-JOINT: Up, Down, Left
			else if (getTerrain(row, col+1).isWallExtension && getTerrain(row, col-1).isWallExtension
					&& !getTerrain(row+1, col).isWallExtension && getTerrain(row-1, col).isWallExtension )
			{ offset = 9; }
			
			//10. T-JOINT: Up, Down, Right
			else if (getTerrain(row, col+1).isWallExtension && getTerrain(row, col-1).isWallExtension
					&& getTerrain(row+1, col).isWallExtension && !getTerrain(row-1, col).isWallExtension )
			{ offset = 10; }
						
			return thisTile.displayTileNumber + offset;			
		}
		else
		{
			return thisTile.displayTileNumber;
		}
	}
	
	public void quit()
	{
		System.exit(0);
	}

	public Vector<String> getMessageLog() {
		return gameState.messageLog;
	}
	
	public void addMessage(String newMessage) {
		gameState.messageLog.add(newMessage);
	}

	public Terrain getTerrain(int xLoc, int yLoc)
	{
		if (!gameState.validateLocation(xLoc,yLoc)) { return terrainFactory.createVoid(); }		
		return gameState.map.terrain[xLoc][yLoc];
	}
	
	public Mob getMob(int xLoc, int yLoc) {		
		if (!gameState.validateLocation(xLoc,yLoc)) {return null;}
		return gameState.map.mobs[xLoc][yLoc];
	}
	
	public Item getTopItem(int xLoc, int yLoc)
	{
		if (!gameState.validateLocation(xLoc,yLoc)) {return null;}
		if (gameState.map.items[xLoc][yLoc] == null) {return null;}
		return gameState.map.items[xLoc][yLoc];
	}
	
	public Player getPlayer(){
		return gameState.player;
	}
	
	public int getPlayerHealth() {
		return gameState.player.currentHP;
	}
	
	public int getPlayerMaxHP() {
		return getPlayer().maxHP;
	}
}
